#!/usr/bin/env python2.7
# -*- coding:utf-8 -*-

"""
@file           pys.py

@description    Python study 

@author         Kevin Zhang (kevin.misc.10@gmail.com)

@date           2011-12-18
"""

import os
import sys
import re
import xml.dom.minidom
from xml.dom.minidom import Node
import inspect
import xml.sax.handler

from unittest import TestCase
from unittest import TestSuite
from unittest import TextTestRunner

SERVICE_XML = 'network_service.xml'

class MyClass:
    def __init__(self) :
        pass

    def private_function(self) :
        try :
            function_call = inspect.stack()[1][4][0].strip()
            #print inspect.stack()
            #print function_call 

            # See if the function_call has "self." in the begining
            matched = re.match( '^self\.', function_call)
            if not matched :
                print 'This is Private Function, Go Away'
                return
        except:
            print 'This is Private Function, Go Away'
            return

        # This # is the real Function, only accessible inside class
        print 'Hey, Welcome into function'

    def public_function(self) :
        # I can call private function from inside the class
        self.private_function()

def test_priv_func():
    my = MyClass()
    my.public_function()
    my.private_function()

    pass

class NetworkAccount(object):
    '''
    service,    the service can be accessed with this account
    '''
    def __init__(self, username, passwd, accountid=None):
        self.__username = username
        self.__passwd = passwd
        self.__accountid = accountid
        pass

    def __str__(self):
        return '{0:<8}:{1:<12}'.format(self.__username, self.__passwd)

    def get_username(self):
        return self.__username

    def get_passwd(self):
        return self.__passwd

    def get_accountid(self):
        return self.__accountid

class NetworkAccountTest(TestCase):
    def setUp(self):
        self.network_account = NetworkAccount('haiyuzha', 'lab', '001')

        pass

    def test_account(self):
        print self.network_account.get_username()
        print self.network_account.get_passwd()
        print self.network_account.get_accountid()

        pass

    def runTest(self):
        self.test_account()
        pass

    def tearDown(self):
        pass

class IPAddress(object):
    IP_VER_4 = '4'
    IP_VER_6 = '6'
    def __init__(self, ip, version=None):
        self.ip = ip

        if version:
            self.__version = version
        else:
            self.__version = IPAddress.IP_VER_4

        pass

    def __str__(self):
        return '{0:>39}'.format(self.ip)

    def __equal__(self, ip):
        equal = False

        return equal

class NetworkService(object):
    NS_SERVICE_FTP = 'ftp'
    NS_SERVICE_TELNET = 'telnet'
    NS_SERVICE_TFTP = 'tftp'
    NS_KNOWN_SERVICE = (
        NS_SERVICE_FTP,
        NS_SERVICE_TELNET,
        NS_SERVICE_TFTP
    )
    def __init__(self, service_name, ipaddr=None, interface_ip=None,
                 account_id=None):
        self.service_name = service_name
        self.ipaddr = IPAddress(ipaddr)
        self.account_id = account_id
        pass

class FTPService(NetworkService):
    def __init__(self, service_name, ipaddr, accountid):
        NetworkService.__init__(self, service_name, ipaddr, accountid)
        pass

    def __str__(self):
        return '{0:>12}@{1}'.format(self.service_name, self.ipaddr)

class TelnetService(NetworkService):
    def __init__(self, service_name, ipaddr, accountid):
        NetworkService.__init__(self, service_name, ipaddr, accountid)
        pass

    def __str__(self):
        return '{0:>12}@{1}'.format(self.service_name, self.ipaddr)

class TFTPService(NetworkService):
    def __init__(self, service_name, ipaddr, accountid):
        NetworkService.__init__(self, service_name, ipaddr, accountid)
        pass

    def __str__(self):
        return '{0:>12}@{1}'.format(self.service_name, self.ipaddr)

class NetworkServer(object):
    def __init__(self, host):
        object.__init__(self)

        # sanity on host value
        if not isinstance(host, tuple):
            print type(host)
            return

        self.__host_name = host[0]

        self.__default_service = NetworkService(NetworkService.NS_SERVICE_FTP)
        self.__service = self.bring_up_services(host)

        self.__default_account = NetworkAccount('', '')

    def __str__(self):
        service_str_list = list()
        return ''
        #service_str_list.append(self.__host_name + ':\n')
        for service in self.__service:
            service_str_list.append(str(service) + '\n')
            pass
        return ''.join(service_str_list)

    def bring_up_services(self, host):
        service_list = list()

        for (service_name, ipaddr, accountid) in host[1]:
            if service_name == NetworkService.NS_SERVICE_FTP:
                service = FTPService(service_name, ipaddr, accountid)
            elif service_name == NetworkService.NS_SERVICE_TELNET:
                service = TelnetService(service_name, ipaddr, accountid)
            elif service_name == NetworkService.NS_SERVICE_TFTP:
                service = TFTPService(service_name, ipaddr, accountid)
            else:
                print 'Unkown service name %s' % (service_name)
                continue

            service_list.append(service)
            #print service

        return service_list

    def is_service_available(self, service_name):
        return False

class AccountManager(object):
    def __init__(self, accounts):
        object.__init__(self)

        self.__accounts = self.collect_account(accounts)

        pass

    def collect_account(self, accounts):
        accountstmp = list()
        for a in accounts:
            accountstmp.append(NetworkAccount(*a))
            pass

        return accountstmp 

    def get_account_num(self):
        return len(self.__accounts)

    def get_account_by_id(self, accountid):
        account = None

        for a in self.__accounts:
            if a[2] == accountid:
                account = a
                break;

        return account

class ServiceXMLHandler(xml.sax.handler.ContentHandler):
    ''' Host service data structure:
            {
                'hosts' : {
                    host : [
                        (service_name, ip, accountid),     # services
                        ......
                    ]
                    ......
                },
                'accounts' : [
                    (accountid, username, passwd)
                    ......
                ]
            }
    '''
    def __init__(self):
        global g_network_services

        self.__in_netservice = False

        self.__in_hosts = False
        self.__in_host = False
        self.__in_host_name = False
        self.__in_host_service = False
        self.__in_host_service_name = False
        self.__in_host_service_ip = False
        self.__in_host_service_accountid = False

        self.__in_accounts = False
        self.__in_account_username = False
        self.__in_account_passwd = False
        self.__in_account_service = False

        self.netservice = {'hosts' : dict(), 'accounts' : list()}
        self.__hosts = self.netservice['hosts'] 
        self.__accounts = self.netservice['accounts']

        g_network_services = self.netservice

    def startElement(self, name, attr):
        if name == 'netserver':
            self.__in_netservice = True

        elif name == 'hosts':
            self.__in_hosts = True

        elif name == 'host':
            self.__in_host = True

            name = attr.getValueByQName('name')

            self.service = list()
            self.__hosts[name] = self.service

        elif name == 'service':
            self.__in_host_service = True

        elif name == 'name':
            self.__in_host_service_name = True

        elif name == 'ipaddr':
            self.__in_host_service_ip = True

        elif name == 'accountid':
            self.__in_host_service_accountid = True

        elif name == 'accounts':
            self.__in_accounts = True

        elif name == 'account':
            self.accountid = attr.getValueByQName('id')

            self.__in_account = True
        elif name == 'username':
            self.__in_account_username = True

        elif name == 'passwd':
            self.__in_account_passwd = True

        else:
            print 'Unkown start element "%s"' % (name)

    def characters(self, data):
        if data:
            if self.__in_host:
                pass

            if self.__in_host_service:
                pass

            if self.__in_host_service_name:
                self.service_name = data

            if self.__in_host_service_ip:
                self.service_ip = data

            if self.__in_host_service_accountid:
                self.service_accountid = data

            if self.__in_account_username:
                self.account_username = data

            if self.__in_account_passwd:
                self.account_passwd = data

    def endElement(self, name):
        if name == 'netserver':
            self.__in_netservice = False

        elif name == 'hosts':
            self.__in_hosts = False

        elif name == 'host':
            self.__in_host = False

        elif name == 'service':
            self.service.append((self.service_name, self.service_ip,
                                 self.service_accountid))
            self.__in_service = False

        elif name == 'name':
            self.__in_host_service_name = False

        elif name == 'ipaddr':
            self.__in_host_service_ip = False

        elif name == 'accountid':
            self.__in_host_service_accountid = False

        elif name == 'accounts':
            self.__in_accounts = False

        elif name == 'account':
            self.__accounts.append((self.accountid, self.account_username,
                                    self.account_passwd))
            self.__in_account = False

        elif name == 'username':
            self.__in_account_username = False

        elif name == 'passwd':
            self.__in_account_passwd = False

        else:
            print 'Unkown end element "%s"' % (name)

def load_service(service_xml):
    global g_network_services

    rc = False

    parser = xml.sax.make_parser()
    handler = ServiceXMLHandler()
    parser.setContentHandler(handler)

    try:
        a = parser.parse(service_xml)
        rc = True
    except xml.sax._exceptions.SAXParseException, e:
        print e
    else:
        pass
        #print g_network_services 
    finally:
        pass

    return rc

'''
    # minidom solution
    service_doc = xml.dom.minidom.parse(service_xml)

    mapping = {}

    for host_node in service_doc.getElementsByTagName('host'):
        #print dir(host_node)
        for service_node in host_node.getElementsByTagName('service'):
            #print dir(service_node)
            for child in service_node.childNodes:
                print child.nodeType,
                if child.nodeType == Node.TEXT_NODE:
                    print child.data
                #if child.nodeName
            #for service_node in host_node.getElementsByTagName('service'):
            pass
    return False
'''

def usage():
    print "usage: fcp put|get ob0vm|ob1vm [file]"

def main():
    global g_network_services

    ts = TestSuite()
    ts.addTest(NetworkAccountTest())
    TextTestRunner(verbosity=2).run(ts)

    if not load_service(SERVICE_XML):
        print 'Failed to parse "%s"' % (SERVICE_XML)

    server_list = list()
    for host in g_network_services['hosts'].iteritems():
        server = NetworkServer(host)
        server_list.append(server)

    account_mgr = AccountManager(g_network_services['accounts'])
    print account_mgr.get_account_num()

    test_priv_func()

    pass

if __name__ == '__main__':
    main()
    sys.exit(0)


